#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "preferences.h"



#define TAB_IMAGE	0
#define TAB_RESULT	1
#define TAB_ABOUT	3


//---------------------------------------
MainWindow::MainWindow (const QString &documentPath, CenteredWidget *parent) :
    QMainWindow (parent),
    ui (new Ui::MainWindow)
{
    ui->setupUi (this);
//	QToolButton*

    m_config = new Config (0); // avant toute chose
    m_sessionManager = new SessionManager (Config::sessionsConfPath (), QSettings::IniFormat, this);
    m_fileDialog = new QFileDialog ();

    setAcceptDrops (true);

    // icônes
    ui->openImage->setIcon (QIcon::fromTheme ("document-open", QIcon (":/images/document-open.svg")));
    ui->acquireFromScanner->setIcon (QIcon::fromTheme ("scanner", QIcon (":/images/scanner.svg")));
    ui->rotateLeft->setIcon (QIcon::fromTheme ("object-rotate-left", QIcon (":/images/object-rotate-left.svg")));
    ui->rotateRight->setIcon (QIcon::fromTheme ("object-rotate-right", QIcon (":/images/object-rotate-right.svg")));
    ui->runOCR->setIcon (m_config->appIcon ());
    ui->editRedo->setIcon (QIcon::fromTheme ("edit-redo", QIcon (":/images/edit-redo.svg")));
    ui->editUndo->setIcon (QIcon::fromTheme ("edit-undo", QIcon (":/images/edit-undo.svg")));
    ui->exit->setIcon (QIcon::fromTheme ("application-exit", QIcon (":/images/application-exit.svg")));
    ui->options->setIcon (QIcon::fromTheme ("preferences-desktop", QIcon (":/images/preferences-desktop-personal.svg")));
    ui->help->setIcon (QIcon::fromTheme ("help-contents", QIcon ("://images/help-contents.svg")));
    ui->extractFromPDF->setIcon (QIcon::fromTheme ("application-pdf", QIcon (":/images/gnome-mime-application-pdf.svg")));
    ui->zoomBestFit1->setIcon (QIcon::fromTheme ("zoom-fit", QIcon (":/images/zoom-fit.svg")));
    ui->zoomBestFit2->setIcon (QIcon::fromTheme ("zoom-fit", QIcon (":/images/zoom-fit.svg")));
    ui->zoomOriginal1->setIcon (QIcon::fromTheme ("zoom-original", QIcon (":/images/zoom-original.svg")));
    ui->zoomOriginal2->setIcon (QIcon::fromTheme ("zoom-original", QIcon (":/images/zoom-original.svg")));


    // images
    m_gv1 = ui->graphicsView1;
    m_gv2 = ui->graphicsView2;

    m_pixmapItem2 = new QGraphicsPixmapItem ();
    m_scene2 = new BasicScene ();
    m_scene2->setBackgroundBrush (QBrush (Qt::lightGray));
    m_scene2->addItem (m_pixmapItem2);

    m_scene1 = new Scene (m_pixmapItem2);

    m_gv1->setScene (m_scene1);
    m_gv2->setScene (m_scene2);

    m_document = new Document (m_sessionManager, this);


    ui->scale->setRange (0.1, 3.0);
    ui->scale->setSingleStep (0.1);
    ui->scale->setDecimals (1);
    ui->scale->setValue (1.0);
    ui->scale->setToolTip (tr ("Changer l'échelle"));

    ui->contrast->setRange (1, 99);
    ui->contrast->setSingleStep (1);
    ui->contrast->setValue (50);
    ui->contrast->setToolTip (tr ("Réglage du contraste de l'aperçu"));

    //------------------------------------------
    setWindowTitle (QString ("%1 - version %2")
                    .arg (Config::appName ())
                    .arg (Config::appVersion ()));

    setWindowIcon (Config::appIcon ());
    initMenuScan ();

    clear ();

    if (m_config->optionRememberGeometry ())
    {
        resize (m_config->windowSize ());
        move (m_config->windowPos ());
        if (m_config->windowIsMinimized ())
            showMinimized ();
        if (m_config->windowIsMaximized ())
            showMaximized ();
        ui->splitter->restoreState (m_config->lastSplitterState ());
    }

    initConnect (); //-----------


    if (not documentPath.isEmpty ())
    {
        open (documentPath);
    }
    else
    {
        if (m_config->optionRestoreWorkSession ())
        {
            m_document->openLastDocument ();
        }
    }

}
//------------------------
MainWindow::~MainWindow ()
{
    delete ui;
    delete m_config;
}
//------------------------------------------------------------------------------
void MainWindow::initConnect ()
{
    connect (m_scene1,
             SIGNAL(zoomed(qreal)),
             m_document,
             SLOT(onZoomed1(qreal)));

    connect (m_scene2,
             SIGNAL(zoomed(qreal)),
             m_document,
             SLOT(onZoomed2(qreal)));

    connect (m_document,
             SIGNAL(empty(bool)),
             this,
             SLOT(onDocumentIsEmpty(bool)));

    connect (m_document,
             SIGNAL(zoom1Changed(qreal)),
             m_scene1,
             SLOT(setZoom(qreal)));

    connect (m_document,
             SIGNAL(zoom2Changed(qreal)),
             m_scene2,
             SLOT(setZoom(qreal)));

    connect (m_document,
             SIGNAL (pathChanged (QString)),
             this,
             SLOT(onPathChanged(QString)));

    connect (m_document,
             SIGNAL (originalPixmapAvailable (QPixmap)),
             this,
             SLOT(onOriginalPixmapAvailable(QPixmap)));

    connect (m_document,
             SIGNAL (previewPixmapAvailable (QPixmap)),
             this,
             SLOT(onPreviewPixmapAvailable(QPixmap)));

    connect (m_document,
             SIGNAL(typePdfChanged(bool)),
             this,
             SLOT(onTypePdfChanged(bool)));

    connect (m_document,
             SIGNAL(pageRangeChanged(int,int)),
             this,
             SLOT(onPageRangeChanged(int,int)));

    connect (m_document,
             SIGNAL(currentPageChanged(int)),
             this,
             SLOT(onCurrentPageChanged(int)));

    connect (m_document,
             SIGNAL(rotationChanged(int)),
             this,
             SLOT(onRotationChanged(int)));

    connect (m_document,
             SIGNAL(scaleChanged(double)),
             this,
             SLOT(onScaleChanged(double)));

    connect (m_document,
             SIGNAL(contrastChanged(int)),
             this,
             SLOT(onContrastChanged(int)));

    connect (m_document,
             SIGNAL(optionCleanImageChanged(bool)),
             this,
             SLOT(onOptionCleanImageChanged(bool)));

    connect (m_document,
             SIGNAL(rectsChanged(QList<QRect>,QList<QRect>)),
             m_scene1,
             SLOT(onCreatePartsFrom(QList<QRect>,QList<QRect>)));

    connect(m_scene1,
            SIGNAL(rectsHaveChanged(QList<QRect>,QList<QRect>)),
            m_document,
            SLOT(setRectLists (QList<QRect>,QList<QRect>)));

    connect (m_scene1,
             SIGNAL(askInformationsAboutCurrentImage()),
             m_document,
             SLOT(onAskInformationsAboutCurrentImage()));

    connect (ui->pdfPage,
             SIGNAL(changed(int)),
             m_document,
             SLOT(setPdfCurrentPage(int)));

    connect (ui->openImage,
             SIGNAL(clicked()),
             this,
             SLOT(onActionOpen()));

    connect (ui->rotateLeft,
             SIGNAL(clicked()),
             m_document,
             SLOT(setRotationLeft()));

    connect (ui->rotateRight,
             SIGNAL(clicked()),
             m_document,
             SLOT(setRotationRight()));

    connect (m_sessionManager,
             SIGNAL(undoIsPossible(bool)),
             ui->editUndo,
             SLOT(setEnabled(bool)));

    connect (m_sessionManager,
             SIGNAL(redoIsPossible(bool)),
             ui->editRedo,
             SLOT(setEnabled(bool)));

    connect (ui->removeMargins,
             SIGNAL(clicked(bool)),
             m_document,
             SLOT(setOptionCleanPreview(bool)));

    connect (m_scene1,
             SIGNAL(askExtractionFrom(QRectF)),
             this,
             SLOT(onAskExtractionFrom(QRectF)));

    connect (m_scene1,
             SIGNAL(askOCRFrom(ImagePart*)),
             this,
             SLOT(onAskOCRFrom (ImagePart*)));

    connect (ui->scale,
             SIGNAL(changed(double)),
             m_document,
             SLOT(setScale(double)));

    connect (ui->contrast,
             SIGNAL(changed(int)),
             m_document,
             SLOT(setContrastFromGUI(int)));
}

//------------------------------
void MainWindow::closeEvent (QCloseEvent *event)
{
    m_config->setLastGeometry (pos (), size (), isMaximized (), isMinimized ());
    m_config->setLastSplitterState (ui->splitter->saveState ());
    if (m_config->optionRemoveTemp ())
    {
        removeTemp ();
    }
    QMainWindow::closeEvent (event);
}
//-----------------------------------------------------
void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
    const QMimeData* mimeData = event->mimeData ();

    if (mimeData->hasUrls ())
    {
        event->acceptProposedAction();
    }
}
//--------------------------------------------
void MainWindow::dropEvent(QDropEvent *event)
{
    const QMimeData* mimeData = event->mimeData ();

    if (mimeData->hasUrls ())
    {
        event->acceptProposedAction();
        QList<QUrl> urls (mimeData->urls ());
        open (urls.at (0).toLocalFile ());
    }
}
//-----------------------------
void MainWindow::removeTemp ()
{
    QString workPath (Config::appWorkPath ());
    QDir workDir (workPath);

    QStringList listToRemove (workDir.entryList (QStringList () << "*", QDir::Files | QDir::NoDotAndDotDot));

    foreach (QString fileName, listToRemove)
    {
        QString fullName (workPath + fileName);
        qDebug () << tr ("Suppression de %1").arg (fullName);
        QFile::remove (fullName);
    }
}
//-----------------------------------
void MainWindow::fillOpenMenu ()
{
    QStringList fileList (m_sessionManager->recentFileList (/*m_config->optionRecentFileMax ()*/)); // limiter la liste

    QMenu* menu = new QMenu (tr ("Documents récents"), this);
    if (!fileList.isEmpty ())
    {
        QList<QAction*> actionList;
        foreach (const QString& fileName, fileList)
        {
            QString type (Config::documentLinuxType (fileName));

            if (type.contains ("image") || type.contains ("pdf"))
            {
                QIcon icon (Config::symbol (fileName));
                QAction* action = new QAction (icon, fileName, this);
                connect (action,
                         SIGNAL(triggered()),
                         this,
                         SLOT(openRecentFile()));
                actionList << action;
            }
        }
        menu->addActions (actionList);
    }
    ui->openImage->setMenu (menu);
    ui->openImage->setPopupMode (QToolButton::MenuButtonPopup);
    ui->openImage->adjustSize ();
}
//--------------------------------
void MainWindow::openRecentFile ()
{
    QAction *action = qobject_cast<QAction *>(sender());
    if (action)
    {
        QString path (action->text ());
        QFileInfo fi (path);
        if (not fi.exists ()) return;
        open (path);
    }
}
//-----------------------
void MainWindow::clear ()
{
    ui->fileName->setText (tr ("(Aucun document ouvert)"));
    ui->preview->setText (tr ("(Aucun aperçu)"));
    m_document->clear ();
    m_gv1->setToolTip (QString ());
    ui->scale->setEnabled (false);
    ui->scale->setValue (1.0);
    ui->contrast->setEnabled (false);
    ui->contrast->setValue (50);
    ui->runOCR->setEnabled (false);
    ui->extractFromPDF->setVisible (false);
    ui->pdfPage->setEnabled (false);
    m_gv1->setTransformationAnchor (QGraphicsView::AnchorViewCenter);
    m_gv1->setTransform (QTransform (), false);
    m_gv2->setTransformationAnchor (QGraphicsView::AnchorViewCenter);
    m_gv2->setTransform (QTransform (), false);
    ui->removeMargins->setChecked (false);
    fillOpenMenu ();
}
//---------------------------------
void MainWindow::onActionOpen ()
{
    m_fileDialog->setAcceptMode (QFileDialog::AcceptOpen);
    m_fileDialog->setViewMode (QFileDialog::List);
    m_fileDialog->setDirectory (m_config->lastOpenDocPath ());
    m_fileDialog->setWindowTitle (tr ("Charger une image ou un PDF"));
    m_fileDialog->setNameFilters (Config::loadFilters ());
    m_fileDialog->setNameFilterDetailsVisible (false);
    m_fileDialog->setFileMode (QFileDialog::ExistingFile);
    if (m_fileDialog->exec () == QDialog::Rejected) return;

    QString imageName = m_fileDialog->selectedFiles ().first ();
    QFileInfo fi (imageName);
    if (!fi.exists ()) return;
    m_config->setLastOpenDocPath (fi.absolutePath ());
    open (imageName);
}

//-----------------------------------
void MainWindow::on_options_clicked()
{
    Preferences preferences (m_sessionManager);
    preferences.exec ();
    fillOpenMenu ();
}
//---------------------------------
void MainWindow::on_help_clicked()
{
    m_helpInfoDialog = new HelpInfoDialog ();
    m_helpInfoDialog->setPage (0);
    m_helpInfoDialog->exec ();
    delete m_helpInfoDialog;
}
//--------------------------------
void MainWindow::on_exit_clicked()
{
    close ();
}
//************************ UNDO ******************************
void MainWindow::on_editUndo_clicked ()
{
    m_document->undo ();
}
//-------------------------------------
void MainWindow::on_editRedo_clicked ()
{
    m_document->redo ();
}
//------------------------------------------------
void MainWindow::on_acquireFromScanner_clicked ()
{
    QString fileName = m_config->scannedImageCompleteFileName ();

    setDisabled (true);
    QApplication::processEvents ();
    int exitCode = QDialog::Accepted;

    if (m_config->optionUseXSane ())
    {
        Xsane* process = new Xsane (this);
        fileName = process->run (fileName);
        delete process;
    }
    else
    {
        Scanner* scanner = new Scanner (fileName);
        exitCode = scanner->exec ();
        delete scanner;
    }

    setEnabled (true);
    if (exitCode == QDialog::Accepted)
    {
        m_document->openDocument (fileName);
    }
}
//-----------------------------------
void MainWindow::initMenuScan ()
{
    QMenu* menu = new QMenu (tr ("Application de numérisation"), this);
    QList<QAction*> actionList;
    QAction* action = new QAction (tr ("Utiliser XSane"), this);
    action->setCheckable (true);
    action->setChecked (m_config->optionUseXSane ());
    connect (action,
             SIGNAL(triggered(bool)),
             m_config,
             SLOT(setOptionUseXSane(bool)));
    actionList << action;
    menu->addActions (actionList);
    ui->acquireFromScanner->setMenu (menu);
    ui->acquireFromScanner->setPopupMode (QToolButton::DelayedPopup);
    ui->acquireFromScanner->adjustSize ();
}
//--------------------------------------------------
void MainWindow::open (const QString &documentPath)
{
    clear ();
    m_document->openDocument (documentPath);
}
//------------------------------------------------
void MainWindow::onDocumentIsEmpty(const bool b)
{
    ui->runOCR->setEnabled (not b);
    ui->rotateLeft->setEnabled (not b);
    ui->rotateRight->setEnabled (not b);
    ui->scale->setEnabled (not b);
    ui->contrast->setEnabled (not b);
    ui->zoomBestFit1->setEnabled (not b);
    ui->zoomBestFit2->setEnabled (not b);
    ui->zoomOriginal1->setEnabled (not b);
    ui->zoomOriginal2->setEnabled (not b);
    ui->removeMargins->setEnabled (not b);
    QApplication::processEvents ();
}
//-----------------------------------------------------------
void MainWindow::onPathChanged(const QString &documentPath)
{
    if (documentPath.isEmpty ()) {
        ui->fileName->setText (tr ("(Aucun document ouvert)"));
        ui->preview->setText (tr ("(Aucun aperçu)"));
    }
    else {
        ui->fileName->setText (tr ("Document courant : %1").arg (documentPath));
        ui->preview->setText (tr ("Aperçu"));
    }
}
//---------------------------------------------------------------
void MainWindow::onOriginalPixmapAvailable(const QPixmap &original)
{
    m_scene1->setOriginalPixmap (original);
    m_gv1->setToolTip (m_document->rotatedProperties ());
}
//-------------------------------------------------------------
void MainWindow::onPreviewPixmapAvailable(const QPixmap &preview)
{
    m_scene1->setPreviewPixmap (preview);
    m_gv2->setToolTip (m_document->previewProperties ());
}
//--------------------------------------------------
void MainWindow::onRotationChanged(const int /*rotation*/)
{
}
//-------------------------------------------
void MainWindow::onScaleChanged(const double scale)
{
    if ((ui->scale)->value () != scale)   (ui->scale)->setValue (scale);
}
//-----------------------------------------------
void MainWindow::onContrastChanged(const int contrast)
{
    if ((ui->contrast)->value () != contrast)   (ui->contrast)->setValue (contrast);
}
//----------------------------------------------------
void MainWindow::onOptionCleanImageChanged(const bool clean)
{
    if (ui->removeMargins->isChecked () != clean)   ui->removeMargins->setChecked (clean);
}
//---------------------------------------
void MainWindow::onTypePdfChanged (const bool b)
{
    if (not b)
    {
        ui->pdfPage->setValue (0);
    }
    ui->pdfPage->setVisible (b);
    ui->extractFromPDF->setVisible (b);
    bool PDFcontainsText = m_document->PDFDocContainsText ();
    ui->extractFromPDF->setEnabled (PDFcontainsText);
    m_scene1->setPdf (PDFcontainsText);
}
//-------------------------------------------------------
void MainWindow::onPageRangeChanged(const int first, const int last)
{
    ui->pdfPage->setMinimum (first);
    ui->pdfPage->setMaximum (last);
    ui->pdfPage->setEnabled (last > first);
    ui->pdfPage->setToolTip (tr ("Ce document comporte %1 pages").arg (last));
}
//--------------------------------------------------
void MainWindow::onCurrentPageChanged(const int currentPg)
{
    ui->pdfPage->setValue (currentPg);
}
//----------------------------------
void MainWindow::on_runOCR_clicked()
{
    m_document->onOCRRequired ();
}
//-------------------------------------------
void MainWindow::on_extractFromPDF_clicked ()
{
    m_document->onTextExtractionRequired ();
}
//-------------------------------------------------------
void MainWindow::onAskExtractionFrom(const QRectF& rectF)
{
    m_document->onTextExtractionRequired (rectF);
}
//-------------------------------------------------------
void MainWindow::onAskOCRFrom(ImagePart* part)
{
    m_document->onROIOCRRequired (part);
}
//-------------------------------------------------------
void MainWindow::on_zoomOriginal1_clicked()
{
    m_scene1->setZoomOriginal ();
}
//-------------------------------------------------------
void MainWindow::on_zoomBestFit1_clicked()
{
    m_scene1->setZoomBestFit (m_document->rotatedImage ());
}
//-------------------------------------------------------
void MainWindow::on_zoomOriginal2_clicked()
{
    m_scene2->setZoomOriginal ();
}
//-------------------------------------------------------
void MainWindow::on_zoomBestFit2_clicked()
{
    m_scene2->setZoomBestFit (m_document->previewImage ());
}
//-------------------------------------------------------
